#####################################################################
# File:         Section.py
# Product:      KnowledgeEngine
#
# Copyright:    Copyright (c) 2001, Faulkner Ltd.
# Author:       Brian Oliver
#
# Description:  This file defines the LibraryItem class, a 
#               simple container/proxy for a single component in a
#               library.
#
# See Also:     ComponentContainer, Model
#####################################################################

#####################################################################
## Knowledge Engine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.KnowledgeEngineCore import *
from Products.KnowledgeEngine.ComponentContainer import ComponentContainer, ComponentContainerInfo
from Products.KnowledgeEngine.ComponentContext import ComponentContext
from Products.KnowledgeEngine.Components.Section.Section import Section
from Products.KnowledgeEngine.Model.Model import Model

#####################################################################
## Zope Library Imports
from Globals import DTMLFile
from Globals import Persistent
from ImageFile import ImageFile

#####################################################################
## Python Library Imports
# (none)

#####################################################################
## LibraryItemInfo Class Definition
class LibraryItemInfo(ComponentContainerInfo):
    """
        Defines the class info methods, defining information about
        the class without needing an instance of the class
    """

    #---------------------------------------------------------------#

    def getClassName(self):
        return 'LibraryItem'

    #---------------------------------------------------------------#

    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """
    
        return "Library Item"
        
    #---------------------------------------------------------------#

    def getIdentityType(self):
        """
            Return the identity type.  
        """
        
        return "lib"
        
    #---------------------------------------------------------------#
    
    def getClassIcon(self):
        """
            Return the appropriate icon file for the class.
        """
        
        return ImageFile('www/icon.gif', globals())
        
    #---------------------------------------------------------------#

    def isPermittedInContainer(self, containerClassInfo, containerInstance = None, instance=None):
        """
            ABSTRACT: Returns if class instances (instance) is permitted in 
            the specified container (containerInstance)
            
            NOTE: This is from this class' instance perspective.
        """
        
        #LibraryItems are permitted in ComponentContainers that are NOT Libraries and only 
        #when the containing Environment contains Libraries with components.
        return containerClassInfo.isInstanceOf('ComponentContainer') and not containerClassInfo.isInstanceOf('Library') and (containerInstance == None or (containerInstance <> None and not containerInstance.isInLibrary() and containerInstance.getEnvironment().containsLibraryComponents()))

    #---------------------------------------------------------------#

    def isChildPermitted(self, childClassInfo, childInstance = None):
        """
            Returns if the specified child is permitted as a 
            child of the class' instances.
            
            NOTE: This is from this class' instance perspective.
            
            For component containers, this always overrides what the
            return value from childClassInfo.isPermittedInContainer(...)
        """
        
        #DEFAULT RULE: LibraryItems don't have children (they're a proxy for components!)
        return false

    #---------------------------------------------------------------#

#####################################################################
## LibraryItem Class Definition
class LibraryItem(ComponentContainer):
    """
        Container/Proxy for a Component in a Library
    """

    #---------------------------------------------------------------#

    #TRANSIENT: a ClassInfo implementation instance to provide info about this class
    _CLASSINFO = LibraryItemInfo()

    #---------------------------------------------------------------#

    # DTML Methods
    index_html = DTMLFile('dtml/index_html', globals())
    simplereport_html = DTMLFile('dtml/simplereport_html', globals())
   
    #---------------------------------------------------------------#
    # Volatile Attributes
    _v_ProxiedComponent = None         #internal reference to the library component

    #---------------------------------------------------------------#

    def __init__(self, id, identity, title, guidance, order, showif, reference, content, reportTitle, reportContent, libraryIdentity, componentIdentity):
        "Constructor for the LibraryItem"        

        ComponentContainer.__init__(self, id, identity, title, guidance, order, showif, reference, content, reportTitle, reportContent)

        self.libraryIdentity = libraryIdentity
        self.componentIdentity = componentIdentity

        #a reference to the component from the library
        self._v_ProxiedComponent = None

    #---------------------------------------------------------------#

    def getLibrary(self):
        """
            Returns the library in which the proxied component exists
        """

        return self.getEnvironment().getLibrary(self.libraryIdentity)

    #---------------------------------------------------------------#

    def getComponentContext(self):
        """
            returns a new component context, based on this component
        """

        return ComponentContext(self)

    #---------------------------------------------------------------#

    def getProxiedComponent(self):
        """
            Resolves and returns the proxy component from the library
        """

        #have we already resolved the component?
        if self._v_ProxiedComponent == None:

            #get the library
            library = self.getEnvironment().getLibrary(self.libraryIdentity)

            #get the component from the library
            self._v_ProxiedComponent = library.getComponent(self.componentIdentity)

            #add this component as a dependant of the library
            self._v_ProxiedComponent.addDependant(self.getIdentity(), self, 'libraryitem')

            ###print "DEBUG: LibraryItem.getProxiedComponent(): Resolved Proxied Component"
        
        #return the component
        return self._v_ProxiedComponent

    #---------------------------------------------------------------#

    def onAfterIdentityChange(self, identityMappings):
        """
            Handle Knowledge Engine specific actions after the 
            identity of this object has changed.
            
            The identityMappings dictionary holds 
            mappings from oldIdentities -> newIdentities
            (including this object)
                        
        """

        #perform default processing
        ComponentContainer.onAfterIdentityChange(self, identityMappings)
        
        #has the proxied library identity changed?
        if identityMappings.has_key(self.libraryIdentity):
            self.libraryIdentity = identityMappings[self.libraryIdentity]
            self._v_ProxiedComponent = None
        
        #has the proxied component identity changed?
        if identityMappings.has_key(self.componentIdentity):
            self.componentIdentity = identityMappings[self.componentIdentity]
            self._v_ProxiedComponent = None

    #---------------------------------------------------------------#
    #####                     PROXY METHODS                     #####
    #---------------------------------------------------------------#
    # (proxy all available methods from the library component here)

    def getTitle(self):
        """
            Return the title of the proxy component
        """
        return self.getProxiedComponent().getTitle()

    #---------------------------------------------------------------#

    def setTitle(self, title):
        """
            Set the title of the proxy component
        """
        self.getProxiedComponent().setTitle(title)
    
    #---------------------------------------------------------------#
                
    def getDescendantsInContext(self, componentContext = None):
        """
            Returns the descendants of the container as a 
            dictionary, indexed by GenericObject.getIdentity(componentContext)
            
            NOTE: takes component contexts into account!
        """

        #get the proxy component
        proxiedComponent = self.getProxiedComponent()

        #do we have a proxied component? (it may be missing!)
        if proxiedComponent != None:
            #create a component context
            componentContext = self.getComponentContext()

            #add the proxied component itself to the result
            result = {proxiedComponent.getIdentity(componentContext) : proxiedComponent}

            #is the proxied component a container?
            if isinstance(proxiedComponent, ComponentContainer):
                result.update(proxiedComponent.getDescendantsInContext(componentContext))
        else:
            result = {}
            
        return result

    #---------------------------------------------------------------#

    def onAfterAdd(self, componentContext = None):
        """
            Handle Knowledge Engine specific actions after this component
            has been added to a container.

            In particular, call the onAfterAdd for the proxy component
            and any of it's children.  This allows the proxy component
            (and descendants) to register dependancies and register
            themselves with the model.
        """

        ###print "DEBUG: LibraryItem.onAfterAdd: Commenced"

        #perform the default onAfterAdd processing
        ComponentContainer.onAfterAdd(self, componentContext)

        #create a component context
        componentContext = self.getComponentContext()

        #get the descendants 
        descendants = self.getDescendantsInContext(componentContext)

        #call onAfterAdd for each of the descendants
        for componentIdentity in descendants.keys():
        
            #get the component
            component = descendants[componentIdentity]

            #call onAfterAdd for the component
            component.onAfterAdd(componentContext)            

        ###print "DEBUG: LibraryItem.onAfterAdd: Completed"

    #---------------------------------------------------------------#

    def onBeforeDelete(self, componentContext = None):
        """
            Handle Knowledge Engine specific actions before this component is deleted

            In particular, call the onBeforeDelete for the proxy component
            and any of it's children.  This allows the proxy component
            (and descendants) to deregister dependancies and deregister
            themselves with the model.
        """

        ###print "DEBUG: LibraryItem.onBeforeDelete: Commenced"

        #perform the default onBeforeDelete processing
        ComponentContainer.onBeforeDelete(self, componentContext)

        #create a component context
        componentContext = self.getComponentContext()

        #get the descendants 
        descendants = self.getDescendantsInContext(componentContext)

        #call onBeforeDelete for each of the descendants
        for componentIdentity in descendants.keys():
        
            #get the component
            component = descendants[componentIdentity]

            #call onAfterAdd for the component
            component.onBeforeDelete(componentContext)            

        ###print "DEBUG: LibraryItem.onBeforeDelete: Completed"
        
    #---------------------------------------------------------------#

    def onAfterClone(self, identityMappings = {}):
        """
            Handle Knowledge Engine specific actions after this component
            has been cloned.

            In particular, reregister the proxy component
            and any of it's children with the model.

            This allows the proxy component (and descendants) to
            register dependancies and register themselves with the model.            
        """

        ###print "DEBUG: LibraryItem.onAfterClone: Commenced"

        #perform the default onAfterClone processing
        ComponentContainer.onAfterClone(self, identityMappings)

        #create a component context
        componentContext = self.getComponentContext()

        #get the descendants 
        descendants = self.getDescendantsInContext(componentContext)

        #call onAfterClone for each of the descendants
        for componentIdentity in descendants.keys():
        
            #get the component
            component = descendants[componentIdentity]

            #call onAfterClone for the component
            component.onAfterClone(identityMappings, componentContext)            

        ###print "DEBUG: LibraryItem.onAfterClone: Completed"

    #---------------------------------------------------------------#
                
#####################################################################
## Class Initialisation

manage_addLibraryItemForm = DTMLFile('dtml/manage_addLibraryItemForm', globals())

def manage_addLibraryItem(self, id, title="LibraryItem", guidance="", order=1.0, showif="", reference="", content="", reportTitle="", reportContent="", libraryIdentity="", componentIdentity="", REQUEST=None):
    """Create and add a LibraryItem to its container/folder"""

    identity = generateIdentity(LibraryItem.identity_type)
    
    obj = LibraryItem(id, identity, title, guidance, order, showif, reference, content, reportTitle, reportContent, libraryIdentity, componentIdentity)
    
    self._setObject(id, obj)
    
    if REQUEST is not None:
        try: 
            url = self.DestinationURL()
        except: 
            url = REQUEST['URL1']        
        REQUEST.RESPONSE.redirect(url + '/manage_main')  

# Register Component Information with the Knowledge Engine
registerGenericObjectClass(LibraryItem, manage_addLibraryItemForm, manage_addLibraryItem)

#####################################################################
